#include "PlayerEvent.h"
#include "Log.h"
#include "ChestFortify.h"

#include "GameSingleton.h"
#include "GameRegistry.hpp"

#include "Blocks/ChestBlock.h"
#include "Player/PlayerData.h"
#include "Components/ComponentBody.h"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentBlockEntity.h"
#include "Components/ComponentMiner.h"

#include "Network/PackageManager.h"
#include "Network/Packages/MessagePackage.h"

#include "Subsystems/SubsystemTerrain.h"

namespace CXHGT
{

    PlayerEvent::PlayerEvent(ChestFortify * chestFortify) : m_chestFortify(chestFortify)
    {
        m_subsystemTerrain = GameSingleton::singletonPtr->getSingleton<SubsystemTerrain>();
    }

    static void sendMessage(ClientPtr client, const std::string & message)
    {
        std::shared_ptr<MessagePackage> package = std::make_shared<MessagePackage>(message);
        package->client = client;
        package->sendType = PackageSendType::TARGET;
        GameSingleton::packageManager->addSendPackageToQueue(package);
    }

    bool PlayerEvent::playerPlaceBlock(ComponentPlayer *componentPlayer, const Point3 &point, int32_t placeBlockValue)
    {
        if (m_subsystemTerrain->getCellContents(point) == ChestBlock::Index() && m_chestFortify->isOwner(point, componentPlayer->playerData->playerGuid) == false)
        {
            sendMessage(componentPlayer->playerData->client, "该箱子已经上锁了，无法在该位置放置其它方块");
            return false;
        }
        return true;
    }

    bool PlayerEvent::playerBreakBlock(ComponentPlayer *componentPlayer, const Point3 &point, int32_t digBlockValue, int32_t toolLevel)
    {
        if (m_subsystemTerrain->getCellContents(point) == ChestBlock::Index())
        {
            if (m_chestFortify->breakChest(point, componentPlayer->playerData->playerGuid) == false)
            {
                sendMessage(componentPlayer->playerData->client, "破坏失败，请再次尝试");
                return false;
            }
        }
        return true;
    }

    bool PlayerEvent::openPointInventory(std::shared_ptr<PlayerData> playerData, const Point3 &point, IInventory *inventory)
    {
        if (inventory->blockEntity != nullptr)
        {
            if (m_chestFortify->isOwner(point, playerData->playerGuid) == false)
            {
                sendMessage(playerData->client, "这不是你的箱子，无法打开，不过你可以尝试破坏");
                return false;
            }
            else
            {
                IInventory *playerInventory = playerData->componentPlayer->componentMiner->inventory;
                int32_t slotValue = playerInventory->getSlotValue(playerInventory->getActiveSlotIndex());
                if (slotValue == m_chestFortify->lockBlockValue)
                {
                    uint32_t num = playerInventory->removeSlotItems(playerInventory->getActiveSlotIndex(), 1);
                    if (num != 0)
                    {
                        uint32_t count = m_chestFortify->addChestFortify(point, playerData->playerGuid, m_chestFortify->addFortifyCount);
                        if (count > 0)
                        {
                            sendMessage(playerData->client, fmt::format("成功上锁箱子，其他玩家需要挖掉{}下才能破坏箱子", count));
                        }
                    }
                }
            }
        }
        return true;
    }

    bool PlayerEvent::playerHandleMoveItem(std::shared_ptr<PlayerData> playerData, IInventory *sourceInventory, uint32_t sourceSlotIndex, IInventory *targetInventory, int32_t targetSlotIndex, uint32_t count)
    {
        if (sourceInventory->blockEntity != nullptr)
        {
            const Point3& point = sourceInventory->blockEntity->coordinates;
            if (m_chestFortify->isOwner(point, playerData->playerGuid) == false)
            {
                sendMessage(playerData->client, "这不是你的箱子，无法操作，不过你可以尝试破坏");
                return false;
            }
        }
        return true;
    }

    bool PlayerEvent::playerHandleDragDrop(std::shared_ptr<PlayerData> playerData, IInventory *sourceInventory, uint32_t sourceSlotIndex, DragMode dragMode, IInventory *targetInventory, uint32_t targetSlotIndex, bool processingOnly)
    {
        if (sourceInventory->blockEntity != nullptr)
        {
            const Point3& point = sourceInventory->blockEntity->coordinates;
            if (m_chestFortify->isOwner(point, playerData->playerGuid) == false)
            {
                sendMessage(playerData->client, "这不是你的箱子，无法操作，不过你可以尝试破坏");
                return false;
            }
        }
        return true;
    }

    bool PlayerEvent::playerDrapDrop(ComponentPlayer *componentPlayer, const Vector3 &dropVelocity, IInventory *inventory, uint32_t slotIndex, uint32_t count)
    {
        if (inventory->blockEntity != nullptr)
        {
            const Point3& point = inventory->blockEntity->coordinates;
            if (m_chestFortify->isOwner(point, componentPlayer->playerData->playerGuid) == false)
            {
                sendMessage(componentPlayer->playerData->client, "这不是你的箱子，无法操作，不过你可以尝试破坏");
                return false;
            }
        }
        return true;
    }

} // namespace BedWars
